home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Lib / mimetools.py < prev    next >
Text File  |  1996-01-29  |  4KB  |  188 lines

  1. # Various tools used by MIME-reading or MIME-writing programs.
  2.  
  3.  
  4. import os
  5. import rfc822
  6. import string
  7. import tempfile
  8.  
  9.  
  10. # A derived class of rfc822.Message that knows about MIME headers and
  11. # contains some hooks for decoding encoded and multipart messages.
  12.  
  13. class Message(rfc822.Message):
  14.  
  15.     def __init__(self, fp, seekable = 1):
  16.         rfc822.Message.__init__(self, fp, seekable)
  17.         self.encodingheader = \
  18.             self.getheader('content-transfer-encoding')
  19.         self.typeheader = \
  20.             self.getheader('content-type')
  21.         self.parsetype()
  22.         self.parseplist()
  23.  
  24.     def parsetype(self):
  25.         str = self.typeheader
  26.         if str == None:
  27.             str = 'text/plain'
  28.         if ';' in str:
  29.             i = string.index(str, ';')
  30.             self.plisttext = str[i:]
  31.             str = str[:i]
  32.         else:
  33.             self.plisttext = ''
  34.         fields = string.splitfields(str, '/')
  35.         for i in range(len(fields)):
  36.             fields[i] = string.lower(string.strip(fields[i]))
  37.         self.type = string.joinfields(fields, '/')
  38.         self.maintype = fields[0]
  39.         self.subtype = string.joinfields(fields[1:], '/')
  40.  
  41.     def parseplist(self):
  42.         str = self.plisttext
  43.         self.plist = []
  44.         while str[:1] == ';':
  45.             str = str[1:]
  46.             if ';' in str:
  47.                 # XXX Should parse quotes!
  48.                 end = string.index(str, ';')
  49.             else:
  50.                 end = len(str)
  51.             f = str[:end]
  52.             if '=' in f:
  53.                 i = string.index(f, '=')
  54.                 f = string.lower(string.strip(f[:i])) + \
  55.                     '=' + string.strip(f[i+1:])
  56.             self.plist.append(string.strip(f))
  57.             str = str[end:]
  58.  
  59.     def getplist(self):
  60.         return self.plist
  61.  
  62.     def getparam(self, name):
  63.         name = string.lower(name) + '='
  64.         n = len(name)
  65.         for p in self.plist:
  66.             if p[:n] == name:
  67.                 return rfc822.unquote(p[n:])
  68.         return None
  69.  
  70.     def getencoding(self):
  71.         if self.encodingheader == None:
  72.             return '7bit'
  73.         return string.lower(self.encodingheader)
  74.  
  75.     def gettype(self):
  76.         return self.type
  77.  
  78.     def getmaintype(self):
  79.         return self.maintype
  80.  
  81.     def getsubtype(self):
  82.         return self.subtype
  83.  
  84.  
  85.  
  86.  
  87. # Utility functions
  88. # -----------------
  89.  
  90.  
  91. # Return a random string usable as a multipart boundary.
  92. # The method used is so that it is *very* unlikely that the same
  93. # string of characters will every occur again in the Universe,
  94. # so the caller needn't check the data it is packing for the
  95. # occurrence of the boundary.
  96. #
  97. # The boundary contains dots so you have to quote it in the header.
  98.  
  99. _prefix = None
  100.  
  101. def choose_boundary():
  102.     global _generation, _prefix, _timestamp
  103.     import time
  104.     import rand
  105.     if _prefix == None:
  106.         import socket
  107.         import os
  108.         hostid = socket.gethostbyname(socket.gethostname())
  109.         uid = `os.getuid()`
  110.         pid = `os.getpid()`
  111.         seed = `rand.rand()`
  112.         _prefix = hostid + '.' + uid + '.' + pid
  113.     timestamp = `int(time.time())`
  114.     seed = `rand.rand()`
  115.     return _prefix + '.' + timestamp + '.' + seed
  116.  
  117.  
  118. # Subroutines for decoding some common content-transfer-types
  119.  
  120. # XXX This requires that uudecode and mmencode are in $PATH
  121.  
  122. def decode(input, output, encoding):
  123.     if decodetab.has_key(encoding):
  124.         pipethrough(input, decodetab[encoding], output)
  125.     else:
  126.         raise ValueError, \
  127.               'unknown Content-Transfer-Encoding: %s' % encoding
  128.  
  129. def encode(input, output, encoding):
  130.     if encodetab.has_key(encoding):
  131.         pipethrough(input, encodetab[encoding], output)
  132.     else:
  133.         raise ValueError, \
  134.               'unknown Content-Transfer-Encoding: %s' % encoding
  135.  
  136. uudecode_pipe = '''(
  137. TEMP=/tmp/@uu.$$
  138. sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
  139. cat $TEMP
  140. rm $TEMP
  141. )'''
  142.  
  143. decodetab = {
  144.     'uuencode':        uudecode_pipe,
  145.     'x-uuencode':        uudecode_pipe,
  146.     'quoted-printable':    'mmencode -u -q',
  147.     'base64':        'mmencode -u -b',
  148. }
  149.  
  150. encodetab = {
  151.     'x-uuencode':        'uuencode tempfile',
  152.     'uuencode':        'uuencode tempfile',
  153.     'quoted-printable':    'mmencode -q',
  154.     'base64':        'mmencode -b',
  155. }
  156.  
  157. def pipeto(input, command):
  158.     pipe = os.popen(command, 'w')
  159.     copyliteral(input, pipe)
  160.     pipe.close()
  161.  
  162. def pipethrough(input, command, output):
  163.     tempname = tempfile.mktemp()
  164.     try:
  165.         temp = open(tempname, 'w')
  166.     except IOError:
  167.         print '*** Cannot create temp file', `tempname`
  168.         return
  169.     copyliteral(input, temp)
  170.     temp.close()
  171.     pipe = os.popen(command + ' <' + tempname, 'r')
  172.     copybinary(pipe, output)
  173.     pipe.close()
  174.     os.unlink(tempname)
  175.  
  176. def copyliteral(input, output):
  177.     while 1:
  178.         line = input.readline()
  179.         if not line: break
  180.         output.write(line)
  181.  
  182. def copybinary(input, output):
  183.     BUFSIZE = 8192
  184.     while 1:
  185.         line = input.read(BUFSIZE)
  186.         if not line: break
  187.         output.write(line)
  188.